#include <iostream>
#include <fstream>
#include <vector>
#include <string.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

using namespace std;

#define largo_palabras 6

class Palabra {
	public:
	char palabra[largo_palabras]; //puede ser string??
	float frec;
};

string eliminarSignosPuntacion(string word) {
	string sigPunt = "!\"#$%&'()*+,-./0123456789:;<=>?@\[]^_`{}|~−";
	bool salir = true;
	while (salir) {
		if (sigPunt.find(word[0]) != string::npos || sigPunt.find(word[1]) != string::npos) {//cout << word[0] <<endl;cout << sigPunt.find(word[0])<<endl;
			if (word.size() > 1) word = word.substr(1);
			else {
				word.clear();
				salir = false;
				}
		} else salir = false;
		//cout << " ------"<< word << endl;
	}
	salir = true;
	if (word.size()) {
		while (salir) { //cout << word[word.size()-1] <<endl;cout << sigPunt.find(word[word.size()])<<endl;
			if (sigPunt.find(word[word.size()]) != string::npos || sigPunt.find(word[word.size()-1]) != string::npos) {
				word.pop_back();
			} else salir = false;
		}
	}
	//cout << "word: "<< word <<endl;
	return word;
}

int busquedaBinaria(string word, vector<string> stop_words) {
	int Iarriba = stop_words.size()-1;
	int Iabajo = 0;
	int Icentro;
	while (Iabajo <= Iarriba) {
		Icentro = (Iarriba + Iabajo)/2;
		if (stop_words[Icentro] == word) return Icentro;
		else {
			if (word < stop_words[Icentro]) Iarriba = Icentro - 1;
			else Iabajo = Icentro + 1;
		}
	}
	return -1;
}

bool esStop_Word (string word, vector<string> stop_words) {
	if (busquedaBinaria(word, stop_words) == -1) return false;
	return true;	
}

void agregarEnSuLugar (vector<Palabra> palabras_a_mergear, Palabra word, int pos_donde_agregar) {
	std::vector<Palabra>::iterator it = palabras_a_mergear.begin();
	palabras_a_mergear.insert(it+pos_donde_agregar, word);
	cout << palabras_a_mergear.size() <<endl;
}

vector<Palabra> actualizarVector (vector<Palabra> palabras_a_mergear, string palab_act) {
	for (int i= 0; i < (int)palab_act.size(); i++) {
		if (palab_act[i] >= 'A' && palab_act[i] <= 'Z') palab_act[i] -= 'A' - 'a';
		if (palab_act[i] < 'a' || palab_act[i] > 'z') palab_act[i] = 0;
	}
	if (!palabras_a_mergear.size()) {
		Palabra word;
		strcpy(word.palabra, palab_act.data());
		word.frec = 1;
		std::vector<Palabra>::iterator it = palabras_a_mergear.begin();
		palabras_a_mergear.insert(it+0, word);  
		return palabras_a_mergear;
	}
	int Iarriba = palabras_a_mergear.size()-1;
	int Iabajo = 0;
	int Icentro, flag = 0;
	int pos_donde_agregar = -1;
	while (Iabajo <= Iarriba) { //cout << "lal" <<endl;cout << Iabajo <<endl; cout << Iarriba <<endl;
		if (Iabajo == Iarriba) pos_donde_agregar = Iabajo;
		Icentro = (Iarriba + Iabajo)/2;
		if (Icentro >= (int)palabras_a_mergear.size()) {flag = 1; break; }
		if (palabras_a_mergear[Icentro].palabra == palab_act) {palabras_a_mergear[Icentro].frec++; return palabras_a_mergear;}
		else {
			if (palab_act.compare(palabras_a_mergear[Icentro].palabra) < 0) Iarriba = Icentro - 1;
			else Iabajo = Icentro + 1;
			//cout << (strncmp(palab_act.data(),palabras_a_mergear[Icentro].palabra, 4)) <<endl; cout << palab_act <<endl; cout << palabras_a_mergear[Icentro].palabra <<endl;
			//cout <<"Iabajo: " <<Iabajo <<endl; cout <<"Iarriba: "<< Iarriba <<endl; cout <<"Icentro: "<< Icentro <<endl;
		}
	}
	//cout << "lala" <<endl;
	if (pos_donde_agregar == -1) {
		if (Iarriba == -1) Iarriba++;
		pos_donde_agregar = Iarriba; 
		//if (palabras_a_mergear.size() == 14) {cout << "aca probwwelm: " <<endl; cout << palab_act <<endl;cout << palabras_a_mergear[pos_donde_agregar].palabra << endl;cout << pos_donde_agregar << endl;cout << Iarriba << endl;}
	}
	if (!flag && palabras_a_mergear[pos_donde_agregar].palabra < palab_act) pos_donde_agregar++; 
	Palabra word;
	strcpy(word.palabra, palab_act.data());
	//word.palabra = palab_act.data();
	word.frec = 1; //cout << "pos_donde_agregar: " << pos_donde_agregar<<endl;
	std::vector<Palabra>::iterator it = palabras_a_mergear.begin();
	palabras_a_mergear.insert(it+pos_donde_agregar, word);
	if ((int)palabras_a_mergear[0].palabra[0] == 0) palabras_a_mergear.erase(palabras_a_mergear.begin());
	return palabras_a_mergear;
}

vector<Palabra> parsearDocumento (string path, vector<string> stop_words ) {
	std::vector<Palabra> palabras_a_mergear; // doc = vector de palabras.
	int total_palabras = 0;
	// se lee el archivo y se lo pone  en un buffer
	std::fstream fs (path.data(), std::fstream::in);
	if (!fs.good()) return palabras_a_mergear;
	cout << path.data()<<" " <<fs << endl;
	fs.seekg(0, fs.end);
	int length = fs.tellg(); //cout << length << endl;
	fs.seekg(0, fs.beg);
	char buffer[length];
	fs.read(buffer,length);
	fs.close();            //cout << buffer << endl;
	// se empieza a parsear el buffer
	string palabra_actual;
	for (int i = 0; i < length; i++) { 
		if (buffer[i] != ' ' && buffer[i] != '\n' && buffer[i]>=0) {palabra_actual.push_back(buffer[i]);}// cout << (int)buffer[i] << (int)'\n'<< endl;}
		else {                                                   //cout << palabra_actual.size() <<endl;            
			if (palabra_actual.size()) total_palabras++;
			if (palabra_actual.size() > 3) {
				if (palabra_actual.size() > 6) palabra_actual = palabra_actual.substr(0,6);//cout << palabra_actual <<endl;    
				palabra_actual = eliminarSignosPuntacion(palabra_actual);
				if (palabra_actual.size()) {//cout << palabra_actual <<endl;
					if (!esStop_Word(palabra_actual, stop_words)) {
						if (palabra_actual.size() > 3) {
							//if (total_palabras == 700 ) return palabras_a_mergear;
							//if (palabra_actual.data() == "\n") cout << i <<endl;
							palabras_a_mergear = actualizarVector(palabras_a_mergear, palabra_actual);  //si existe ya le agrega uno a la frec,
							//cout << palabra_actual <<endl;
							//cout << palabras_a_mergear.size() <<endl;
							//int e = 0; while (e< 30000000) e++;
							}
						}														// sino la agrega con frec 1.
					}
				}
			palabra_actual.clear();
		}
	}
	//cout << "palabras_a_mergear.size(): "<<palabras_a_mergear.size() <<endl;
	for (std::vector<Palabra>::iterator it = palabras_a_mergear.begin(); it != palabras_a_mergear.end(); ++it) {//cout << "llega aca" <<endl;
		//cout << (*it).palabra << " " << strlen((*it).palabra)<< " " << (*it).frec << endl;
		//cout << total_palabras << endl;
		//if ((int)((*it).palabra[0]) == 0) cout <<"ENTER\n";
		(*it).frec = ((*it).frec / total_palabras);
		//cout << (*it).palabra << " " << (*it).frec << endl;
	}
	//escribir en nuevo archivo con el nombre del archivo.
	return palabras_a_mergear;
}

vector<string> leerStopWords(string path) {
	vector<string> stop_words;
	std::fstream fs (path.data(), std::fstream::in);
	fs.seekg(0, fs.end);
	int length = fs.tellg(); //cout << length <<endl;
	fs.seekg(0, fs.beg);
	char buffer[length];
	fs.read(buffer,length);
	fs.close();
	string stopWord_actual;
	for (int i = 0; i < length; i++) {
		if (buffer[i] != '\n') stopWord_actual.push_back(buffer[i]);
		else {
			stop_words.push_back(stopWord_actual); //cout << stopWord_actual << endl;
			stopWord_actual.clear();
		}
	}
	return stop_words;
}

